import os
import platform
import subprocess
import ctypes
from typing import Dict, List


class PermissionChecker:
    """系统权限检查器"""

    def __init__(self):
        self.system = platform.system()
        self.is_admin = self._check_admin_privileges()

    def _check_admin_privileges(self) -> bool:
        """检查是否具有管理员权限"""
        try:
            if self.system == "Windows":
                return ctypes.windll.shell32.IsUserAnAdmin() != 0
            else:
                return os.geteuid() == 0
        except Exception:
            return False

    def check_required_permissions(self, scan_env: str = "host") -> Dict[str, any]:
        """检查扫描所需的权限

        Args:
            scan_env: 扫描环境 ('host', 'wsl', 'docker')

        Returns:
            Dict: 权限检查结果
        """
        result = {
            "has_permission": True,
            "warnings": [],
            "errors": [],
            "recommendations": [],
        }

        # 检查基本权限
        self._check_basic_permissions(result)

        # 根据扫描环境检查特定权限
        if scan_env == "host":
            self._check_host_permissions(result)
        elif scan_env == "wsl":
            self._check_wsl_permissions(result)
        elif scan_env == "docker":
            self._check_docker_permissions(result)

        return result

    def _check_basic_permissions(self, result: Dict[str, any]):
        """检查基本权限"""
        # 检查网络访问权限
        if not self._can_access_network():
            result["errors"].append("无法访问网络，请检查网络连接")
            result["has_permission"] = False

        # 检查文件系统权限
        if not self._can_write_temp():
            result["warnings"].append("无法写入临时文件，可能影响结果导出功能")

    def _check_host_permissions(self, result: Dict[str, any]):
        """检查本机扫描权限"""
        if self.system == "Windows":
            # Windows下检查是否有足够权限获取进程信息
            if not self.is_admin:
                result["warnings"].append(
                    "当前不是管理员权限，可能无法获取完整的进程信息"
                )
                result["recommendations"].append(
                    "建议以管理员身份运行程序以获取更详细的进程信息"
                )

            # 检查防火墙设置
            if self._check_windows_firewall_blocking():
                result["warnings"].append("Windows防火墙可能会阻止某些端口扫描")
                result["recommendations"].append(
                    "如需扫描被防火墙保护的端口，请临时调整防火墙设置"
                )

        elif self.system in ["Linux", "Darwin"]:
            # Unix系统下检查权限
            if not self.is_admin:
                result["warnings"].append(
                    "当前不是root权限，可能无法扫描某些系统端口(1-1024)"
                )
                result["recommendations"].append("扫描系统端口(1-1024)可能需要sudo权限")

    def _check_wsl_permissions(self, result: Dict[str, any]):
        """检查WSL权限"""
        if self.system != "Windows":
            result["errors"].append("WSL仅在Windows系统上可用")
            result["has_permission"] = False
            return

        # 检查WSL是否安装
        if not self._is_wsl_available():
            result["errors"].append("WSL未安装或未启用")
            result["has_permission"] = False
            result["recommendations"].append(
                "请安装并启用WSL: https://docs.microsoft.com/zh-cn/windows/wsl/install"
            )

        # 检查WSL发行版
        distros = self._get_wsl_distros()
        if not distros:
            result["errors"].append("未找到可用的WSL发行版")
            result["has_permission"] = False
            result["recommendations"].append("请安装至少一个WSL发行版，如Ubuntu")

    def _check_docker_permissions(self, result: Dict[str, any]):
        """检查Docker权限"""
        # 检查Docker是否安装
        if not self._is_docker_available():
            result["errors"].append("Docker未安装或未运行")
            result["has_permission"] = False
            result["recommendations"].append("请安装并启动Docker Desktop")
            return

        # 检查Docker权限
        if not self._can_access_docker():
            result["errors"].append("无法访问Docker，可能需要管理员权限")
            result["has_permission"] = False
            result["recommendations"].append(
                "请确保当前用户有权限访问Docker，或以管理员身份运行"
            )

        # 检查运行中的容器
        containers = self._get_docker_containers()
        if not containers:
            result["warnings"].append("未找到运行中的Docker容器")
            result["recommendations"].append("请确保要扫描的Docker容器正在运行")

    def _can_access_network(self) -> bool:
        """检查网络访问权限"""
        try:
            import socket

            # 尝试创建socket
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(1)
            sock.close()
            return True
        except Exception:
            return False

    def _can_write_temp(self) -> bool:
        """检查临时文件写入权限"""
        try:
            import tempfile

            with tempfile.NamedTemporaryFile(delete=True) as tmp:
                tmp.write(b"test")
            return True
        except Exception:
            return False

    def _check_windows_firewall_blocking(self) -> bool:
        """检查Windows防火墙是否可能阻止扫描"""
        if self.system != "Windows":
            return False

        try:
            # 检查防火墙状态
            result = subprocess.run(
                ["netsh", "advfirewall", "show", "allprofiles", "state"],
                capture_output=True,
                text=True,
                timeout=5,
            )
            return "ON" in result.stdout.upper()
        except Exception:
            return False

    def _is_wsl_available(self) -> bool:
        """检查WSL是否可用"""
        try:
            result = subprocess.run(
                ["wsl", "--list", "--quiet"], capture_output=True, text=True, timeout=5
            )
            return result.returncode == 0
        except Exception:
            return False

    def _get_wsl_distros(self) -> List[str]:
        """获取WSL发行版列表"""
        try:
            result = subprocess.run(
                ["wsl", "--list", "--quiet"], capture_output=True, text=True, timeout=5
            )
            if result.returncode == 0:
                distros = [
                    line.strip()
                    for line in result.stdout.strip().split("\n")
                    if line.strip()
                ]
                return [d for d in distros if d and not d.startswith("Windows")]
            return []
        except Exception:
            return []

    def _is_docker_available(self) -> bool:
        """检查Docker是否可用"""
        try:
            result = subprocess.run(
                ["docker", "--version"], capture_output=True, text=True, timeout=5
            )
            return result.returncode == 0
        except Exception:
            return False

    def _can_access_docker(self) -> bool:
        """检查是否能访问Docker"""
        try:
            result = subprocess.run(
                ["docker", "ps"], capture_output=True, text=True, timeout=10
            )
            return result.returncode == 0
        except Exception:
            return False

    def _get_docker_containers(self) -> List[str]:
        """获取Docker容器列表"""
        try:
            result = subprocess.run(
                ["docker", "ps", "--format", "{{.Names}}"],
                capture_output=True,
                text=True,
                timeout=10,
            )
            if result.returncode == 0:
                return [
                    line.strip()
                    for line in result.stdout.strip().split("\n")
                    if line.strip()
                ]
            return []
        except Exception:
            return []

    def get_permission_summary(self, scan_env: str = "host") -> str:
        """获取权限检查摘要"""
        result = self.check_required_permissions(scan_env)

        summary = []

        if result["has_permission"]:
            summary.append("✅ 权限检查通过")
        else:
            summary.append("❌ 权限检查失败")

        if result["errors"]:
            summary.append("\n错误:")
            for error in result["errors"]:
                summary.append(f"  • {error}")

        if result["warnings"]:
            summary.append("\n警告:")
            for warning in result["warnings"]:
                summary.append(f"  • {warning}")

        if result["recommendations"]:
            summary.append("\n建议:")
            for rec in result["recommendations"]:
                summary.append(f"  • {rec}")

        return "\n".join(summary)
